package __goroutines

import (
	"fmt"
	"sync"
	atomic2 "sync/atomic"
)

// 原子操作
func atomic() {
	var ops int64

	var wg sync.WaitGroup

	for i := 0; i < 50; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for i := 0; i < 1000; i++ {
				// 对ops进行原子操作
				// 文档里不推荐这么写，在不同的协程里操作共享数据要非常小心
				atomic2.AddInt64(&ops, 1)
			}
		}()
	}
	wg.Wait()
	fmt.Println("ops=", ops)
}

type Container struct {
	mu       sync.Mutex
	counters map[string]int
}

func (c *Container) inc(name string) {
	c.mu.Lock()         // 加锁
	defer c.mu.Unlock() // 解锁
	c.counters[name]++
}

// 给数据加锁
func mutex() {
	c := Container{
		counters: map[string]int{"a": 0, "b": 0},
	}
	var wg sync.WaitGroup
	doIncrement := func(name string, n int) {
		for i := 0; i < n; i++ {
			c.inc(name)
		}
		wg.Done()
	}
	wg.Add(3)
	go doIncrement("a", 10000)
	go doIncrement("a", 10000)
	go doIncrement("b", 10000)
	wg.Wait()
	fmt.Println(c.counters)
}
